<?php

/**
 * @see Smithy_Navigation_Item
 */
require_once 'Smithy/Navigation/Item.php';

/**
 * Navigation component.
 */
class Smithy_Navigation implements Iterator, Countable
{
    const LOGIN_REQUIRED = 'loginRequired';
    const LOGIN_NOT_REQUIRED = 'loginNotRequired';
    const LOGIN_FORBIDDEN = 'loginForbidden';

    protected $_items = array();
    protected $_actualItemKey = null;
    protected $_loginRequirement = Smithy_Navigation::LOGIN_NOT_REQUIRED;
    protected $_viewScript = null;
    protected $_className = 'Smithy-Navigation';
    protected $_defaultItemClass = 'Smithy-Navigation-Item';
    protected $_defaultActiveItemClass = 'Smithy-Navigation-Active-Item';
    protected $_viewScriptPath = null;
    protected $_view = null;
    protected $_auth = null;
    protected static $_instance = null;

    /**
     * Constructor
     *
     * Ensures singleton pattern.
     * @return void
     */
    protected function __construct ()
    {}

    /**
     * Singleton pattern.
     *
     * @return Smithy_Navigation
     */
    public static function getInstance(){
        if (null === self::$_instance) {
            self::$_instance = new Smithy_Navigation();
        }
        return self::$_instance;
    }

    /**
     * Adds a new navigation item to the menu.
     *
     * @param string $key
     * @param Smithy_Navigation_Item $item
     * @return Smithy_Navigation
     */
    public function addItem($key, Smithy_Navigation_Item $item)
    {
        $this->_items[$key] = $item->setNavigation($this);
        return $this;
    }

    /**
     * Renders the navigation object.
     *
     * @return string
     */
    public function render()
    {
        if (Smithy_Navigation::LOGIN_REQUIRED === $this->_loginRequirement) {
            if (null === $this->getAuth() or !$this->getAuth()->hasIdentity()) {
                return '';
            }
        } elseif(Smithy_Navigation::LOGIN_FORBIDDEN === $this->_loginRequirement) {
            if ($this->getAuth()->hasIdentity()) {
                return '';
            }
        }

        $source = '<ul class="' . $this->getClassName() . '" >';
        foreach ($this as $key => $item) {
            $item->setIsActive($this->_actualItemKey === $key);
            $source .= $item->render();
        }
        $source .= '</ul>';
        return $source;
    }

    /**
     * Returns the navigation item requested by its key.
     *
     * @param string $key
     * @return Smithy_Navigation_Item
     */
    public function getItemByKey($key)
    {
        if (array_key_exists($key, $this->_items)) {
            return $this->_items[$key];
        }

        return null;
    }

    /**
     * Returns the menu's class attribute.
     *
     * @return string
     */
    public function getClassName ()
    {
        return $this->_className;
    }

    /**
     * Returns the active item's class attribute.
     *
     * @return string
     */
    public function getDefaultActiveItemClass ()
    {
        return $this->_defaultActiveItemClass;
    }

    /**
     * Returns the item's default class attribute.
     *
     * @return string
     */
    public function getDefaultItemClass ()
    {
        return $this->_defaultItemClass;
    }

    /**
     * The view object.
     *
     * @return Zend_View
     */
    public function getView ()
    {
        return $this->_view;
    }

    /**
     * The menu view script.
     *
     * @return string
     */
    public function getViewScript ()
    {
        return $this->_viewScript;
    }

    /**
     * Path to the view scripts.
     *
     * @return string
     */
    public function getViewScriptPath ()
    {
        return $this->_viewScriptPath;
    }

    /**
     * Returns the auth object.
     *
     * @return Zend_Auth
     */
    public function getAuth()
    {
        return (null === $this->_auth ? Zend_Auth::getInstance() : $this->_auth);
    }

    /**
     * Sets the menu's class attribute.
     *
     * @param string $_className
     * @return Smithy_Navigation
     */
    public function setClassName ($className)
    {
        $this->_className = $className;
        return $this;
    }

    /**
     * Sets the active item's class attribute.
     *
     * @param string $_defaultActiveItemClass
     * @return Smithy_Navigation
     */
    public function setDefaultActiveItemClass ($defaultActiveItemClass)
    {
        $this->_defaultActiveItemClass = $defaultActiveItemClass;
        return $this;
    }

    /**
     * Sets the items' class attribute.
     *
     * @param string $_defaultItemClass
     * @return Smithy_Navigation
     */
    public function setDefaultItemClass ($_defaultItemClass)
    {
        $this->_defaultItemClass = $_defaultItemClass;
        return $this;
    }

    /**
     * Sets the menu's login requirement.
     *
     * @param string $_loginRequirement
     * @return Smithy_Navigation
     */
    public function setLoginRequirement ($loginRequirement)
    {
        $this->_loginRequirement = $loginRequirement;
        return $this;
    }

    /**
     * Sets the view to render the menu.
     *
     * @param Zend_View $_view
     * @return Smithy_Navigation
     */
    public function setView ($view)
    {
        $this->_view = $view;
        return $this;
    }

    /**
     * Sets the menu view script.
     *
     * @param string $_viewScript
     * @return Smithy_Navigation
     */
    public function setViewScript ($viewScript)
    {
        $this->_viewScript = $viewScript;
        return $this;
    }

    /**
     * Sets the view scripts path.
     *
     * @param string $_viewScriptPath
     * @return Smithy_Navigation
     */
    public function setViewScriptPath ($viewScriptPath)
    {
        $this->_viewScriptPath = $viewScriptPath;
        return $this;
    }

    /**
     * Sets the actual menu item.
     *
     * @return Smithy_Navigation
     */
    public function setActualItemKey($key)
    {
        if (array_key_exists($key, $this->_items)) {
            $this->_actualItemKey = $key;
        }
        return $this;
    }

    /**
     * Sets the auth object.
     *
     * @param Zend_Auth $auth
     * @return Smithy_Navigation
     */
    public function setAuth($auth)
    {
        $this->_auth = $auth;
        return $this;
    }

    /**
     *
     * @see Iterator::current()
     * @return Smithy_Navigation_Item
     */
    public function current ()
    {
        return current($this->_items);
    }

    /**
     *
     * @see Iterator::key()
     */
    public function key ()
    {
        return key($this->_items);
    }

    /**
     *
     * @see Iterator::next()
     */
    public function next ()
    {
        return next($this->_items);
    }

    /**
     *
     * @see Iterator::rewind()
     */
    public function rewind ()
    {
        return reset($this->_items);
    }

    /**
     *
     * @see Iterator::valid()
     */
    public function valid ()
    {
        return (bool)$this->current();
    }

    /**
     *
     * @see Countable::count()
     */
    public function count ()
    {
        return count($this->_items);
    }
}
